﻿namespace Sidvall.Data
{
    public static class DataTypeManager
    {
        #region GetDataType

        #region GetDataType

        public static DataType GetDataType(System.Type type)
        {
            if (type == null)
                return DataType.Object;
            if (Sidvall.SystemContext.Current.CodeManager.IsNullableType(type))
                type = type.GenericTypeArguments[0];
            return GetDataTypeFromTypeName(type.Name);
        }

        #endregion
        #region GetDataTypeFromTypeName

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
        public static DataType GetDataTypeFromTypeName(string typeName)
        {
            if (string.IsNullOrWhiteSpace(typeName))
                return DataType.Object;
            switch (typeName.ToLowerInvariant())
            {
                case "system.boolean":
                case "boolean":
                case "bool":
                    return DataType.Boolean;
                case "system.char":
                case "char":
                    return DataType.Char;
                case "system.datetime":
                case "datetime":
                    return DataType.DateTime;
                case "system.datetimeoffset":
                case "datetimeoffset":
                    return DataType.DateTimeOffset;
                case "system.decimal":
                case "decimal":
                    return DataType.Decimal;
                case "system.double":
                case "double":
                    return DataType.Double;
                case "system.byte":
                case "byte":
                    return DataType.Byte;
                case "system.int16":
                case "int16":
                case "short":
                    return DataType.Int16;
                case "system.int32":
                case "int32":
                case "int":
                    return DataType.Int32;
                case "system.int64":
                case "int64":
                case "long":
                    return DataType.Int64;
                case "system.object":
                case "object":
                    return DataType.Object;
                case "system.sbyte":
                case "sbyte":
                    return DataType.SByte;
                case "system.single":
                case "single":
                case "float":
                    return DataType.Single;
                case "system.string":
                case "string":
                    return DataType.String;
                case "system.timespan":
                case "timespan":
                    return DataType.TimeSpan;
                case "system.uint16":
                case "uint16":
                case "ushort":
                    return DataType.UInt16;
                case "system.uint32":
                case "uint32":
                case "uint":
                    return DataType.UInt32;
                case "system.uint64":
                case "uint64":
                case "ulong":
                    return DataType.UInt64;
                case "system.xml":
                case "xml":
                    return DataType.Xml;
                case "system.guid":
                case "guid":
                    return DataType.Guid;
                case "system.byte[]":
                case "byte[]":
                    return DataType.Binary;
                case "system.data.entity.spatial.dbgeography":
                    return DataType.Geography;
                case "system.data.entity.spatial.dbgeometry":
                    return DataType.Geometry;
                default:
                    return DataType.Object;
            }
        }

        #endregion
        #region GetDataTypeFromValue

        public static DataType GetDataTypeFromValue(object value)
        {
            if (value is bool)
                return DataType.Boolean;
            if (value is char)
                return DataType.Char;
            if (value is System.DateTime)
                return DataType.DateTime;
            if (value is System.DateTimeOffset)
                return DataType.DateTimeOffset;
            if (value is decimal)
                return DataType.Decimal;
            if (value is double)
                return DataType.Double;
            if (value is byte)
                return DataType.Byte;
            if (value is short)
                return DataType.Int16;
            if (value is int)
                return DataType.Int32;
            if (value is long)
                return DataType.Int64;
            if (value is sbyte)
                return DataType.SByte;
            if (value is System.Single)
                return DataType.Single;
            if (value is System.String)
                return DataType.String;
            if (value is System.TimeSpan)
                return DataType.TimeSpan;
            if (value is System.UInt16)
                return DataType.UInt16;
            if (value is System.UInt32)
                return DataType.UInt32;
            if (value is System.UInt64)
                return DataType.UInt64;
            if (value is System.Guid)
                return DataType.Guid;
            if (value is byte[])
                return DataType.Binary;
            if (value is Geography)
                return DataType.Geography;
            if (value is Geometry)
                return DataType.Geometry;
            return DataType.Object;
        }

        #endregion
        #region IsInteger

        public static bool IsInteger(DataType type)
        {
            switch (type)
            {
                case DataType.Byte:
                case DataType.Int16:
                case DataType.Int32:
                case DataType.Int64:
                case DataType.SByte:
                case DataType.UInt16:
                case DataType.UInt32:
                case DataType.UInt64:
                    return true;
                default:
                    return false;
            }
        }

        #endregion
        #region IsNumber

        public static bool IsNumber(DataType type)
        {
            switch (type)
            {
                case DataType.Decimal:
                case DataType.Double:
                case DataType.Byte:
                case DataType.Int16:
                case DataType.Int32:
                case DataType.Int64:
                case DataType.SByte:
                case DataType.UInt16:
                case DataType.UInt32:
                case DataType.UInt64:
                case DataType.Single:
                    return true;
                default:
                    return false;
            }
        }

        #endregion
        #region IsValueType

        public static bool IsValueType(DataType type)
        {
            switch (type)
            {
                case DataType.Boolean:
                case DataType.Char:
                case DataType.DateTime:
                case DataType.DateTimeOffset:
                case DataType.Decimal:
                case DataType.Double:
                case DataType.Byte:
                case DataType.Int16:
                case DataType.Int32:
                case DataType.Int64:
                case DataType.SByte:
                case DataType.Single:
                case DataType.TimeSpan:
                case DataType.UInt16:
                case DataType.UInt32:
                case DataType.UInt64:
                    return true;
                default:
                    return false;
            }
        }

        #endregion

        #endregion
    }
}
